package com.yykj.tencent.im.server.core;

import com.yykj.tencent.im.server.common.ResponseVo;
import com.yykj.tencent.im.server.exception.TimException;
import com.yykj.tencent.im.server.utils.GsonUtil;
import com.yykj.tencent.im.server.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Map;

import java.util.concurrent.ThreadLocalRandom;

@Component
@Slf4j
public class TimUtil {


    private static RedisServiceUtil redisServiceUtil;

    @Resource
    public void setRedisServiceUtil(RedisServiceUtil redisServiceUtil) {
        TimUtil.redisServiceUtil = redisServiceUtil;
    }


    private static final long sdkappid = 1400587167;
    private static final String key = "9efd36997f3b06799111f90d5aaa0564c791b05ac82719efcaed4b9bf857a4d2";

    /**
     * UserSig 签名默认有效时长（秒）
     */
    private static final long DEFAULT_EXPIRE_TIME = 24 * 60 * 60L;
    private static final String FORMAT_URL = "https://%s/%s?sdkappid=%d&identifier=%s&usersig=%s&random=%d&contenttype=json";
    private static final String domain = "console.tim.qq.com";
    private static final String admin = "administrator";
    private static final String REDIS_IM_USER_SIG = "silence:im_user_sig:";

    private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
    private static final OkHttpClient HTTP_CLIENT = new OkHttpClient();

    private static final int reqReTryCount = 3;

    /**
     * 产生随机数
     */
    public static long genRandom(){
        return ThreadLocalRandom.current().nextLong(0, 0x100000000L);
    }





    /**
     * 获取UserSig信息
     * @return
     */
   public static String getUserSig() {
       String userSig = redisServiceUtil.get(REDIS_IM_USER_SIG + admin);
       if (StringUtils.isEmpty(userSig)) {
           TLSSigAPIv2 tlsSigApi = new TLSSigAPIv2(sdkappid, key);
           userSig = tlsSigApi.genUserSig(admin, DEFAULT_EXPIRE_TIME);
           redisServiceUtil.set(REDIS_IM_USER_SIG + admin, userSig, DEFAULT_EXPIRE_TIME);
       }
       return userSig;
   }


    /**
     * 获取请求URL
     * @Param api 请求接口
     * @return
     */
    public static String getUrl(String api) {
        String sig = getUserSig();
        long random = genRandom();
        return String.format(FORMAT_URL, domain, api,
                sdkappid, admin, sig, random);
    }


    /**
     * 通用GET方法
     * @Param api 请求接口
     * @param queryParams   API 地址所需参数(不包含公共参数)
     */
    public static String get(String api,Map<String,String> queryParams) throws TimException {
        String url = getUrl(api);
        if (queryParams != null) {
            Iterator<Map.Entry<String, String>> iterator = queryParams.entrySet().iterator();
            Map.Entry<String, String> entry;
            while (iterator.hasNext()) {
                entry = iterator.next();
                url += "&" + entry.getKey() + "=" + entry.getValue();
            }
        }
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        return execute(request);
    }

    public static <T> T get(String api, Map<String,String> queryParams, Class<T> cls) throws TimException {
        String result = get(api, queryParams);
        return JacksonUtil.json2Object(result, cls);
    }

    /**
     * 通用POST方法
     * @Param api 请求接口
     * @param body          API 请求体
     */
    public static String post(String api,Object body) throws TimException {
        String url = getUrl(api);
        String json = JacksonUtil.objectToJson(body);

        log.debug("【TIMJava】 request method : {}, url：{}", "POST",url);
        log.debug("【TIMJava】 request body : {} ",json);

        Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(JSON, json))
                .build();
        return execute(request);
    }

    public static <T> T post(String api, Object body, Class<T> cls) throws TimException{
        String result = post(api, body);
        return JacksonUtil.json2Object(result, cls);
    }


    private static String execute(Request request) throws TimException {
        return execute(request, 1);
    }

    private static String execute(Request request, int reqCount) throws TimException {
        try {
            log.debug("【TIMJava】 发起请求 当前第 {} 次 / {} 次 {}", reqCount, reqReTryCount, reqCount > 1 ? "[重试请求]" : "");
            return executeInternal(request);
        } catch (SocketTimeoutException e) {
            if (reqCount >= reqReTryCount) {
                throw new TimException("请求失效,请检查你的网络状态");
            }
            // 执行重试
            return execute(request, reqCount++);
        } catch (TimException e) {
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
            throw new TimException(e.getMessage());
        }
        return "";
    }

    private static String executeInternal(Request request) throws TimException, IOException {
        Response response = HTTP_CLIENT.newCall(request).execute();
        String jsonResult = response.body().string();
        ResponseVo baseVo = GsonUtil.fromJson(jsonResult, ResponseVo.class);
        if ( baseVo.getErrorCode() != 0) {
            throw new TimException(baseVo.getErrorInfo());
        }
        return jsonResult;
    }

}
